package android.slc.rx;

import io.reactivex.rxjava3.annotations.NonNull;

import io.reactivex.rxjava3.core.*;
import org.reactivestreams.Publisher;

import io.reactivex.rxjava3.schedulers.Schedulers;


/**
 * @author android.slc
 * @date 2019/10/18 11:07
 */
public class SlcRxJavaUtils {

    private static volatile Scheduler platformScheduler;

    public static void init(Scheduler platformScheduler) {
        if (SlcRxJavaUtils.platformScheduler != platformScheduler) {
            synchronized (SlcRxJavaUtils.class) {
                if (SlcRxJavaUtils.platformScheduler != platformScheduler) {
                    SlcRxJavaUtils.platformScheduler = platformScheduler;
                }
            }
        }
    }

    public static Scheduler getPlatformScheduler() {
        if (platformScheduler == null) {
            synchronized (SlcRxJavaUtils.class) {
                if (platformScheduler == null) {
                    platformScheduler = Schedulers.newThread();
                }
            }
        }
        return platformScheduler;
    }

    /**
     * 使用转换的Android调度器
     *
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<T, T> applyOoAndroidSchedulers() {
        return applyOoIo2AndroidSchedulers();
    }

    /**
     * 使用转换的Android调度器
     *
     * @param <T>
     * @return
     */
    public static <T> FlowableTransformer<T, T> applyOfAndroidSchedulers() {
        return applyOfIo2AndroidSchedulers();
    }

    /**
     * 使用转换的Android调度器
     *
     * @param <T>
     * @return
     */
    public static <T> SingleTransformer<T, T> applyOsAndroidSchedulers() {
        return applyOsIo2AndroidSchedulers();
    }

    /**
     * 使用转换的Android调度器
     *
     * @param <T>
     * @return
     */
    public static <T> MaybeTransformer<T, T> applyOmAndroidSchedulers() {
        return applyOmIo2AndroidSchedulers();
    }

    /**
     * 使用转换的Android调度器
     *
     * @return
     */
    public static CompletableTransformer applyOcAndroidSchedulers() {
        return applyOcIo2AndroidSchedulers();
    }

    /**
     * Observable io
     *
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<T, T> applyOoIo2AndroidSchedulers() {
        return new ObservableTransformer<T, T>() {
            @NonNull
            @Override
            public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Flowable io
     *
     * @param <T>
     * @return
     */
    public static <T> FlowableTransformer<T, T> applyOfIo2AndroidSchedulers() {
        return new FlowableTransformer<T, T>() {
            @NonNull
            @Override
            public Publisher<T> apply(@NonNull Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Single io
     *
     * @param <T>
     * @return
     */
    public static <T> SingleTransformer<T, T> applyOsIo2AndroidSchedulers() {
        return new SingleTransformer<T, T>() {
            @NonNull
            @Override
            public SingleSource<T> apply(@NonNull Single<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Maybe io
     *
     * @param <T>
     * @return
     */
    public static <T> MaybeTransformer<T, T> applyOmIo2AndroidSchedulers() {
        return new MaybeTransformer<T, T>() {
            @NonNull
            @Override
            public MaybeSource<T> apply(@NonNull Maybe<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Completable io
     *
     * @return
     */
    public static CompletableTransformer applyOcIo2AndroidSchedulers() {
        return new CompletableTransformer() {
            @NonNull
            @Override
            public CompletableSource apply(@NonNull Completable upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Observable io
     *
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<T, T> applyOoComputation2AndroidSchedulers() {
        return new ObservableTransformer<T, T>() {
            @NonNull
            @Override
            public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.computation())
                        .unsubscribeOn(Schedulers.computation())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Flowable io
     *
     * @param <T>
     * @return
     */
    public static <T> FlowableTransformer<T, T> applyOfComputation2AndroidSchedulers() {
        return new FlowableTransformer<T, T>() {
            @NonNull
            @Override
            public Publisher<T> apply(@NonNull Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.computation())
                        .unsubscribeOn(Schedulers.computation())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Single io
     *
     * @param <T>
     * @return
     */
    public static <T> SingleTransformer<T, T> applyOsComputation2AndroidSchedulers() {
        return new SingleTransformer<T, T>() {
            @NonNull
            @Override
            public SingleSource<T> apply(@NonNull Single<T> upstream) {
                return upstream.subscribeOn(Schedulers.computation())
                        .unsubscribeOn(Schedulers.computation())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Maybe io
     *
     * @param <T>
     * @return
     */
    public static <T> MaybeTransformer<T, T> applyOmComputation2AndroidSchedulers() {
        return new MaybeTransformer<T, T>() {
            @NonNull
            @Override
            public MaybeSource<T> apply(@NonNull Maybe<T> upstream) {
                return upstream.subscribeOn(Schedulers.computation())
                        .unsubscribeOn(Schedulers.computation())
                        .observeOn(getPlatformScheduler());
            }
        };
    }

    /**
     * Completable io
     *
     * @return
     */
    public static CompletableTransformer applyOcComputation2AndroidSchedulers() {
        return new CompletableTransformer() {
            @NonNull
            @Override
            public CompletableSource apply(@NonNull Completable upstream) {
                return upstream.subscribeOn(Schedulers.computation())
                        .unsubscribeOn(Schedulers.computation())
                        .observeOn(getPlatformScheduler());
            }
        };
    }
}
